package com.glacier.demo.contoller;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.glacier.demo.handle.CustomHandle;
import com.glacier.demo.handle.GlobalFallback;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

/**
 * date 2024-01-29 19:55
 *
 * @author glacier
 * @version 1.0
 */
@Slf4j
@RestController
public class FlowController {

    @PostConstruct
    public void initRule() {
        List<FlowRule> rules = new ArrayList<>();

        FlowRule rule;
        for (int i = 0; i < 20; i++) {
            rule = new FlowRule();
            rule.setResource("/flow" + (i + 1));
            rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
            // Set limit QPS to 20.
            rule.setCount(i % 3 + 1);
            rules.add(rule);
        }

        FlowRuleManager.loadRules(rules);
    }

    @RequestMapping("/flow1")
    public String flow1() {
        try (Entry entry = SphU.entry("flow1")) {
            return "正常访问";
        } catch (BlockException e) {
            log.error("流控了", e);
            return "流控了!";
        }
    }

    @RequestMapping("/flow2")
    @SentinelResource(value = "/flow2", blockHandler = "flowHandleException")
    public String flow2() {
        return "正常访问";
    }

    public String flowHandleException(BlockException ex) {
        log.error("流控了", ex);
        return "流控了";
    }

    /**
     * 流控和fallback 同时满足时，流控优先级高
     *
     * @param id
     * @return
     */
    @RequestMapping("/flow3")
    @SentinelResource(value = "/flow3",
            blockHandlerClass = CustomHandle.class, blockHandler = "blockHandler1",
            fallbackClass = GlobalFallback.class, fallback = "fallback1")
    public String flow3(Long id) {
        long i = 1 / id;
        return "正常访问";
    }

    @RequestMapping("/flow4")
    @SentinelResource(value = "/flow4", blockHandlerClass = CustomHandle.class, blockHandler = "blockHandler2")
    public String flow4(String name) {
        return "正常访问";
    }

    @RequestMapping("/flow5")
    @SentinelResource(value = "/flow5")
    public String flow5(String name) {
        return "正常访问";
    }

}
